#include "toyota.h"
#include "drivers.h"
#include "stdcan.h"

CanTxMsg mToyotaCheckEng =
{
    0x7df, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x02, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mToyotaCheckEngSupport =
{
    0x7e0, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x02, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mToyotaCheckBcmSupport =
{
    0x750, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x40, 0x02, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mToyotaEngContinuePackage =
{
    0x7e0, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x30, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mToyotaBcmContinuePackage =
{
    0x750, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x40, 0x30, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mToyotaEngStream =
{
    0x7e0, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

ToyotaEngData mToyotaEngTable[ENG_DATA_SIZE] =
{
    { ENG_DATA_RPM,           0x01, 0x0a, 2, SUPPORTED },
    { ENG_DATA_VS,            0x01, 0x0c, 1, SUPPORTED },
    { ENG_DATA_ECT,           0x01, 0x09, 1, SUPPORTED },
    { ENG_DATA_IAT,           0x01, 0x06, 1, SUPPORTED },
    { ENG_DATA_APP,           0x41, 0x05, 2, SUPPORTED },
    { ENG_DATA_TP,            0x01, 0x10, 1, SUPPORTED },
    { ENG_DATA_ERT,           0x01, 0x0d, 2, SUPPORTED },
    { ENG_DATA_LOAD,          0x01, 0x01, 2, SUPPORTED },
    { ENG_DATA_BATTVOLT,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_REALFUELCO,    0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_FUELLEVEL,     0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_ODO,           0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_LTFT,          0x03, 0x03, 1, SUPPORTED },
    { ENG_DATA_STFT,          0x03, 0x02, 1, SUPPORTED },
    { ENG_DATA_MISFIRE1,      0x45, 0x05, 1, SUPPORTED },
    { ENG_DATA_MISFIRE2,      0x45, 0x06, 1, SUPPORTED },
    { ENG_DATA_MISFIRE3,      0x45, 0x07, 1, SUPPORTED },
    { ENG_DATA_MISFIRE4,      0x45, 0x08, 1, SUPPORTED },
    { ENG_DATA_MISFIRE5,      0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE6,      0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_FCLS,          0x03, 0x00, 1, SUPPORTED },
    { ENG_DATA_KEYSTATUS,     0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_HO2S1,         0x04, 0x14, 1, SUPPORTED },
    { ENG_DATA_HO2S2,         0x04, 0x18, 1, SUPPORTED },
    { ENG_DATA_MAP,           0x01, 0x05, 1, SUPPORTED },
    { ENG_DATA_INJECTPULSE,   0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_OILPRESSURE,   0x00, 3, 1, UNSUPPORTED },
    { ENG_DATA_OILLEVELSTATUS,0x00, 3, 1, UNSUPPORTED },
};

ToyotaBcmData mToyotaDoorTable[BCM_DOOR_SIZE] =
{
    { BCM_DATA_DDA,             0x40, 0xa2, 0x00, 1,      SUPPORTED },
    { BCM_DATA_PDA,             0x40, 0xa3, 0x00, 1,      SUPPORTED },
    { BCM_DATA_RRDA,            0x40, 0xa2, 0x02, 1,      SUPPORTED },
    { BCM_DATA_LRDA,            0x40, 0xa2, 0x03, 1,      SUPPORTED },
};

ToyotaBcmData mToyotaWindowTable[BCM_WINDOW_SIZE] =
{
    { BCM_DATA_LFWIN,           0xad, 0x01, 0x00, 1,      SUPPORTED },
    { BCM_DATA_RFWIN,           0x91, 0x01, 0x00, 1,      SUPPORTED },
    { BCM_DATA_LRWIN,           0x93, 0x01, 0x00, 1,      SUPPORTED },
    { BCM_DATA_RRWIN,           0x92, 0x01, 0x00, 1,      SUPPORTED },
};

uint16_t mToyotaCanId[CODE_MAX_SIZE] =
{
    0x7e0,          //ENGINE
    0x7e0,          //AT
    0x7b0,          //ABS
    0x780,          //SRS
    0x750,          //BCM
    0x7c0,          //IPC
    0x7a1,          //EPS
    0x7c4,          //AC
    0x000,          //TPMS
};

ToyotaSupportPid mEngSupportList[TOYOTA_SUPPORT_ITEM_MAX];

BcmModuleSupport mLfWinBcmSupport;
BcmModuleSupport mRfWinBcmSupport;
BcmModuleSupport mLrWinBcmSupport;
BcmModuleSupport mRrWinBcmSupport;
BcmModuleSupport mDoorBcmSupport;

__IO uint8_t mEngSupportRawBuffer[RAW_BUF_MAX_SIZE];
__IO uint8_t mBcmSupportRawBuffer[RAW_BUF_MAX_SIZE];
uint8_t mEngSupportDone = FALSE;

VehicleCtrlOps mToyotaCtrlOps;
VehicleProcessOps mToyotaProcessOps;

void toyota_init(Vehicle *vehicle)
{
    uint8_t i;

    mToyotaProcessOps.check_engine_on = toyota_check_engine_on;
    mToyotaProcessOps.get_rpm = toyota_get_rpm;
    mToyotaProcessOps.process_eng_data = toyota_process_eng_data;
    //    mToyotaProcessOps.process_bcm_window_data = toyota_process_bcm_window_data;
    mToyotaProcessOps.clear_fault_code = toyota_clear_fault_code;
    mToyotaProcessOps.get_fault_code = toyota_get_fault_code;

    vehicle->processOps = &mToyotaProcessOps;
    //initialize the var
    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        mEngSupportList[i].pid = 0x00;
        mEngSupportList[i].len = 0;
        memset(mEngSupportList[i].raw_data, 0x00, TOYOTA_SUPPORT_RAW_MAX);
    }
    mLfWinBcmSupport.module_id = LF_WINDOW_MODULE;
    mRfWinBcmSupport.module_id = RF_WINDOW_MODULE;
    mLrWinBcmSupport.module_id = LR_WINDOW_MODULE;
    mRrWinBcmSupport.module_id = RR_WINDOW_MODULE;
    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        mLfWinBcmSupport.supportPid[i].pid = 0x00;
        mLfWinBcmSupport.supportPid[i].len = 0;
        memset(mLfWinBcmSupport.supportPid[i].raw_data, 0x00, TOYOTA_SUPPORT_RAW_MAX);
        mRfWinBcmSupport.supportPid[i].pid = 0x00;
        mRfWinBcmSupport.supportPid[i].len = 0;
        memset(mRfWinBcmSupport.supportPid[i].raw_data, 0x00, TOYOTA_SUPPORT_RAW_MAX);
        mLrWinBcmSupport.supportPid[i].pid = 0x00;
        mLrWinBcmSupport.supportPid[i].len = 0;
        memset(mLrWinBcmSupport.supportPid[i].raw_data, 0x00, TOYOTA_SUPPORT_RAW_MAX);
        mRrWinBcmSupport.supportPid[i].pid = 0x00;
        mRrWinBcmSupport.supportPid[i].len = 0;
        memset(mRrWinBcmSupport.supportPid[i].raw_data, 0x00, TOYOTA_SUPPORT_RAW_MAX);
    }
    mDoorBcmSupport.module_id = DOOR_MODULE;
    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        mDoorBcmSupport.supportPid[i].pid = 0x00;
        mDoorBcmSupport.supportPid[i].len = 0;
        memset(mDoorBcmSupport.supportPid[i].raw_data, 0x00, TOYOTA_SUPPORT_RAW_MAX);
    }

    toyota_bcm_keepalive(mDoorBcmSupport.module_id);
    //toyota_bcm_support(&mDoorBcmSupport);
}

typedef enum {
    STATUS_FIRST_STEP,
    STATUS_RECVING,
    STATUS_END
} CheckSupportStatus;

void toyota_eng_support(void)
{
    uint8_t ret;
    uint16_t i, j;
    uint8_t first;
    uint16_t index;
    uint16_t buf_index = 0;
    uint8_t status;
    uint8_t cp_flag;
    CanRxMsg rxMsg;
    uint8_t len;

    bsp_can_clear();
    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    memset((void *)mEngSupportRawBuffer, 0x00, RAW_BUF_MAX_SIZE);
    status = STATUS_FIRST_STEP;
    while(status != STATUS_END) {
        switch(status) {
            case STATUS_FIRST_STEP:
                //                logi("%s: FIRST STEP", __func__);
                ret = vehicle_can_session(&mToyotaCheckEngSupport, &rxMsg);
                if(ret) {
                    //check the continue package of engine
                    first = rxMsg.Data[0];
                    index = index_of_buf(rxMsg.Data, 8, 0x01);
                    if(first == 0x10) {
                        for(i = index + 1; i < 8; i++) {
                            mEngSupportRawBuffer[buf_index ++] =
                                rxMsg.Data[i];
                        }
                        status = STATUS_RECVING;
                    } else {
                        status = STATUS_END;
                    }
                } else {
                    status = STATUS_END;
                }
                break;
            case STATUS_RECVING:
                //                logi("%s: RECVING", __func__);
                cp_flag = FALSE;
                //send continue package
                bsp_can_send(&mToyotaEngContinuePackage);
                while(!cp_flag) {
                    ret = vehicle_can_recv(&rxMsg);
                    if(ret) {
                        first = rxMsg.Data[0];
                        if(first > 0x20 && first < 0x30) {
                            for(i = 1; i < 8; i++) {
                                mEngSupportRawBuffer[buf_index ++] =
                                    rxMsg.Data[i];
                            }
                        }
                        if(first == 0x10) {
                            first = rxMsg.Data[0];
                            index = index_of_buf(rxMsg.Data, 8, 0x01);
                            for(i = index + 1; i < 8; i++) {
                                mEngSupportRawBuffer[buf_index ++] =
                                    rxMsg.Data[i];
                            }
                            status = STATUS_RECVING;
                            cp_flag = TRUE;
                        }
                    } else {
                        status = STATUS_END;
                        cp_flag = TRUE;
                    }
                }
                break;
            case STATUS_END:
                logi("%s: END", __func__);
                break;
        }
    }
#if 0
    logi("buf_index = %d", buf_index);
    logi("===============================");
    //process buffer
    for(i = 0; i < RAW_BUF_MAX_SIZE; i++) {
        printf("%02x ", mEngSupportRawBuffer[i]);
        if((i + 1) % 20 == 0)
            printf("\r\n");
    }
    logi("===============================");
#endif
    //map to support list
    index = 0;
    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        if(index >= buf_index)
            break;
        mEngSupportList[i].pid = mEngSupportRawBuffer[index ++];
        len = mEngSupportRawBuffer[index ++];
        mEngSupportList[i].len = len;
        if(len > 0) {
            for(j = 0; j < len; j++) {
                mEngSupportList[i].raw_data[j] =
                    mEngSupportRawBuffer[index ++];
            }
            while(mEngSupportRawBuffer[index] == 0x00)
                index ++;
        } else {
            break;
        }
    }
    //dump data
    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        printf("##pid = %02x ", mEngSupportList[i].pid);
        printf("len = %02d -> ", mEngSupportList[i].len);
        for(j = 0; j < mEngSupportList[i].len; j++) {
            printf("%02x ", mEngSupportList[i].raw_data[j]);
        }
        printf("\r\n");
    }

}

void toyota_bcm_support(BcmModuleSupport *moduleSupport)
{
    uint8_t ret;
    uint16_t i, j;
    uint8_t first;
    uint16_t index;
    uint16_t buf_index = 0;
    uint8_t status;
    uint8_t cp_flag;
    CanRxMsg rxMsg;
    uint8_t len;

    bsp_can_clear();
    bsp_can_filter(0x758, 0x758, 0x7ff, 0x7ff);
    os_delay(2);
    memset((void *)mBcmSupportRawBuffer, 0x00, RAW_BUF_MAX_SIZE);
    status = STATUS_FIRST_STEP;
    while(status != STATUS_END) {
        switch(status) {
            case STATUS_FIRST_STEP:
                //                logi("%s: FIRST STEP", __func__);
                mToyotaCheckBcmSupport.Data[0] = moduleSupport->module_id;
                ret = vehicle_can_session(&mToyotaCheckBcmSupport, &rxMsg);
                if(ret) {
                    //check the continue package of bcm
                    first = rxMsg.Data[1];
                    index = index_of_buf(rxMsg.Data, 8, 0x01);
                    if(first == 0x10) {
                        for(i = index + 1; i < 8; i++) {
                            mBcmSupportRawBuffer[buf_index ++] =
                                rxMsg.Data[i];
                        }
                        status = STATUS_RECVING;
                    } else {
                        status = STATUS_END;
                    }
                } else {
                    status = STATUS_END;
                }
                break;
            case STATUS_RECVING:
                //                logi("%s: RECVING", __func__);
                cp_flag = FALSE;
                //send continue package
                mToyotaBcmContinuePackage.Data[0] = moduleSupport->module_id;
                bsp_can_send(&mToyotaBcmContinuePackage);
                while(!cp_flag) {
                    ret = vehicle_can_recv(&rxMsg);
                    if(ret) {
                        first = rxMsg.Data[1];
                        if(first > 0x20 && first < 0x30) {
                            for(i = 2; i < 8; i++) {
                                mBcmSupportRawBuffer[buf_index ++] =
                                    rxMsg.Data[i];
                            }
                        }
                        if(first == 0x10) {
                            first = rxMsg.Data[1];
                            index = index_of_buf(rxMsg.Data, 8, 0x01);
                            for(i = index + 1; i < 8; i++) {
                                mBcmSupportRawBuffer[buf_index ++] =
                                    rxMsg.Data[i];
                            }
                            status = STATUS_RECVING;
                            cp_flag = TRUE;
                        }
                    } else {
                        status = STATUS_END;
                        cp_flag = TRUE;
                    }
                }
                break;
            case STATUS_END:
                logi("%s: END", __func__);
                break;
        }
    }
    os_delay_ms(100);
#if 0
    logi("buf_index = %d", buf_index);
    logi("===============================");
    //process buffer
    for(i = 0; i < RAW_BUF_MAX_SIZE; i++) {
        printf("%02x ", mBcmSupportRawBuffer[i]);
        if((i + 1) % 20 == 0)
            printf("\r\n");
    }
    logi("===============================");
#endif
#if 1
    //map to support list
    index = 0;
    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        if(index >= buf_index)
            break;
        moduleSupport->supportPid[i].pid = mBcmSupportRawBuffer[index ++];
        len = mBcmSupportRawBuffer[index ++];
        moduleSupport->supportPid[i].len = len;
        if(len > 0) {
            for(j = 0; j < len; j++) {
                moduleSupport->supportPid[i].raw_data[j] =
                    mBcmSupportRawBuffer[index ++];
            }
            while(mBcmSupportRawBuffer[index] == 0x00)
                index ++;
        } else {
            break;
        }
    }
    //dump data
    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        printf("##pid = %02x ", moduleSupport->supportPid[i].pid);
        printf("len = %02d -> ", moduleSupport->supportPid[i].len);
        for(j = 0; j < moduleSupport->supportPid[i].len; j++) {
            printf("%02x ", moduleSupport->supportPid[i].raw_data[j]);
        }
        printf("\r\n");
    }
#endif
}

uint8_t toyota_check_engine_on(void)
{
    uint8_t on = FALSE;
    CanRxMsg rxMsg;

    bsp_can_clear();
    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    if(vehicle_can_session(&mToyotaCheckEng, &rxMsg)) {
        on = TRUE;
        if(!mEngSupportDone) {
            mEngSupportDone = TRUE;
            toyota_eng_support();
        }
    } else {
        on = FALSE;
    }
    return on;
}

void toyota_get_rpm(uint16_t *rpm)
{
    StdCanData *data;

    data = (StdCanData *)malloc(sizeof(StdCanData));
    memset(data, 0x00, sizeof(StdCanData));
    data->tx_id = 0x7df;
    data->cmd_len = 0x02;
    data->cmd = 0x01;
    data->id = 0x0c;
    data->rx_id = 0x7e8;
    if(StdCan_ioctl(data)) {
        *rpm = (data->rx_data[1] << 8) | data->rx_data[2];
    } else {
        loge("%s: failed", __func__);
        *rpm = 0;
    }
    free(data);
}

void toyota_process_eng_data(EngineDataMap *dataMap)
{
    uint8_t i, j, k;
    uint8_t ret;
    CanRxMsg rxMsg;
    uint8_t offset;
    uint8_t size;
    uint8_t pid;
    uint8_t first;
    uint8_t second;
    uint16_t index;
    uint16_t buf_index;
    uint8_t temp_buf[128];
    uint8_t package_count = 0;
    uint8_t bytes = 0;
    uint8_t sub_off;
    uint8_t index_of_pid;

    if(!mEngSupportDone)
        return;
    bsp_can_clear();
    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    for(i = 0; i < ENG_DATA_SIZE; i++) {
        os_delay(2);
        vehicle_lock();
        if(!mToyotaEngTable[i].support) {
            vehicle_unlock();
            continue;
        }
        //check the pid is supported
        pid = mToyotaEngTable[i].pid;
        if(!toyota_check_eng_pid_supported(pid)) {
            vehicle_unlock();
            continue;
        }

        size = mToyotaEngTable[i].size;
        offset = mToyotaEngTable[i].offset;
        //send data stream
        mToyotaEngStream.Data[2] = pid;
        buf_index = 0;
        memset(temp_buf, 0x00, 128);
        ret = vehicle_can_session(&mToyotaEngStream, &rxMsg);
        if(ret) {
            first = rxMsg.Data[0];
            second = rxMsg.Data[1];
            index = index_of_buf(rxMsg.Data, 8, pid);
            if(first == 0x10) {
                //long package
                bytes = rxMsg.Data[1];
                package_count = (bytes - 6) / 7;
                if((bytes - 6) % 7 > 0) {
                    package_count ++;
                }
                for(j = index + 1; j < 8; j++) {
                    temp_buf[buf_index ++] = rxMsg.Data[j];
                }
                //send continue package
                bsp_can_send(&mToyotaEngContinuePackage);
                for(j = 0; j < package_count; j++) {
                    ret = vehicle_can_recv(&rxMsg);
                    if(ret) {
                        for(k = 1; k < 8; k++) {
                            temp_buf[buf_index ++] = rxMsg.Data[k];
                        }
                    } else {
                        break;
                    }
                }
            } else if(first != 0x10 && second == 0x61){
                //short package
                for(j = index + 1; j < 8; j++) {
                    temp_buf[buf_index ++] = rxMsg.Data[j];
                }
            } else {
                //error
                vehicle_unlock();
                continue;
            }

            printf("\r\n");
            for(j = 0; j < buf_index; j++) {
                printf("%02x ", temp_buf[j]);
            }
            printf("\r\n");
            //process temp_buf
            //need to sub unsupport items
            for(j = 0; j < TOYOTA_SUPPORT_ITEM_MAX; j++) {
                if(pid == mEngSupportList[j].pid) {
                    index_of_pid = j;
                    break;
                }
            }
            sub_off = 0;
            for(j = 0; j < offset; j++) {
                if(mEngSupportList[index_of_pid].raw_data[j] == 0x00) {
                    sub_off ++;
                }
            }
            offset -= sub_off;
            dataMap->data[i].id = i;
            dataMap->data[i].updated = TRUE;
            dataMap->data[i].len = size;
            memcpy(dataMap->data[i].data, temp_buf + offset, size);
        } else {
            break;
        }
        vehicle_unlock();
    }
}

void toyota_process_bcm_window_data(BcmDataMap *dataMap)
{
    CanRxMsg rxMsg;
    CanTxMsg txMsg =
    {
        0x750, 0x18db33f1,
        CAN_ID_STD, CAN_RTR_DATA,
        8,
        0x90, 0x02, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00
    };
    uint8_t i, j, k;
    uint8_t ret;
    uint8_t offset;
    uint8_t size;
    uint8_t pid;
    uint8_t module_id;
    uint8_t first;
    uint8_t second;
    uint16_t index;
    uint16_t buf_index;
    uint8_t temp_buf[128];
    uint8_t package_count = 0;
    uint8_t bytes = 0;
    uint8_t sub_off;
    uint8_t index_of_pid;

    bsp_can_clear();
    bsp_can_filter(0x758, 0x758, 0x7ff, 0x7ff);
    for(i = 0; i < BCM_WINDOW_SIZE; i++) {
        os_delay_ms(200);
        toyota_bcm_keepalive(mToyotaWindowTable[i].module_id);
        txMsg.Data[0] = mToyotaWindowTable[i].module_id;
        txMsg.Data[3] = mToyotaWindowTable[i].pid;
        if(!mToyotaWindowTable[i].support)
            continue;
        //check the pid is supported
        pid = mToyotaWindowTable[i].pid;
        module_id = mToyotaWindowTable[i].module_id;
        //if(!toyota_check_eng_pid_supported(pid))
        //    continue;

        size = mToyotaWindowTable[i].size;
        offset = mToyotaWindowTable[i].offset;
        //send data stream
        buf_index = 0;
        memset(temp_buf, 0x00, 128);
        ret = vehicle_can_session(&txMsg, &rxMsg);
        if(ret) {
            first = rxMsg.Data[0];
            second = rxMsg.Data[1];
            index = index_of_buf(rxMsg.Data, 8, pid);
            if(first == 0x10) {
                //long package
                bytes = rxMsg.Data[1];
                package_count = (bytes - 6) / 7;
                if((bytes - 6) % 7 > 0) {
                    package_count ++;
                }
                for(j = index + 1; j < 8; j++) {
                    temp_buf[buf_index ++] = rxMsg.Data[j];
                }
                //send continue package
                mToyotaBcmContinuePackage.Data[0] = module_id;
                bsp_can_send(&mToyotaBcmContinuePackage);
                for(j = 0; j < package_count; j++) {
                    ret = vehicle_can_recv(&rxMsg);
                    if(ret) {
                        for(k = 1; k < 8; k++) {
                            temp_buf[buf_index ++] = rxMsg.Data[k];
                        }
                    } else {
                        break;
                    }
                }
            } else if(first != 0x10 && second == 0x61){
                //short package
                for(j = index + 1; j < 8; j++) {
                    temp_buf[buf_index ++] = rxMsg.Data[j];
                }
            } else {
                //error
                continue;
            }

            printf("\r\n");
            for(j = 0; j < buf_index; j++) {
                printf("%02x ", temp_buf[j]);
            }
            printf("\r\n");
            //process temp_buf
        } else {
            break;
        }
    }
}

uint8_t toyota_clear_fault_code(uint8_t type)
{
    uint8_t ret;
    CanRxMsg rxMsg;
    CanTxMsg txMsg =
    {
        0x7e0, 0x18db33f1,
        CAN_ID_STD, CAN_RTR_DATA,
        8,
        0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    CanTxMsg subIdTxMsg =
    {
        0x7e0, 0x18db33f1,
        CAN_ID_STD, CAN_RTR_DATA,
        8,
        0x40, 0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    if(type >= CODE_MAX_SIZE)
        return FALSE;

    bsp_can_clear();
    bsp_can_filter(mToyotaCanId[type], mToyotaCanId[type], 0x7ff, 0x7ff);
    if(type == CODE_BCM) {
        subIdTxMsg.StdId = mToyotaCanId[type];
        if(vehicle_can_session(&subIdTxMsg, &rxMsg)) {
            ret = TRUE;
        } else {
            ret = FALSE;
        }
    } else {
        txMsg.StdId = mToyotaCanId[type];
        if(vehicle_can_session(&txMsg, &rxMsg)) {
            ret = TRUE;
        } else {
            ret = FALSE;
        }
    }

    return ret;
}

void toyota_get_fault_code(uint8_t type, FaultCodeItem *item)
{
    uint8_t ret;
    StdCanData *data;

    data = (StdCanData *)malloc(sizeof(StdCanData));
    memset(data, 0x00, sizeof(StdCanData));
    data->tx_id = mToyotaCanId[type];
    data->cmd_len = 0x02;
    data->cmd = 0x13;
    data->id = 0xb0;
    data->rx_id = mToyotaCanId[type] + 8;

    //send stream msg
    if(StdCan_ioctl(data)) {
        logi("%s: rx bytes = %d", __func__, data->rx_bytes);
    }
    free(data);
}

void toyota_bcm_keepalive(uint8_t module)
{
    CanRxMsg rxMsg;
    CanTxMsg txMsg =
    {
        0x750, 0x18db33f1,
        CAN_ID_STD, CAN_RTR_DATA,
        8,
        0x40, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    txMsg.Data[0] = module;
    bsp_can_clear();
    bsp_can_filter(0x758, 0x758, 0x7ff, 0x7ff);
    if(vehicle_can_session(&txMsg, &rxMsg)) {
    } else {
        loge("keepalive error");
    }
}

uint8_t toyota_check_eng_pid_supported(uint8_t pid)
{
    uint8_t ret = FALSE;
    uint8_t i;

    for(i = 0; i < TOYOTA_SUPPORT_ITEM_MAX; i++) {
        if(pid == mEngSupportList[i].pid) {
            ret = TRUE;
            break;
        }
    }
    return ret;
}

